package momo.multitree.simulation.result;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;

public class ScaledRelativePerformance {
	
	public ScaledRelativePerformance() {
	}
	
	public void getResult(String input, String output) {
		String csvFormat = this.toCSVFormat(input);
		this.writeToFile(output, csvFormat);
	}
	
	private String toCSVFormat(String filename) {
		StringBuffer buffer = new StringBuffer();
		Map<String, Double[]> val = getData(filename);
		for ( String key : val.keySet() ) {
			Double[] d = val.get(key);
			double minLat = min( d[0], d[3], d[6] );
			double maxLat = max( d[0], d[3], d[6] );
			double latRange = maxLat - minLat;
			
			double minCost = min( d[1], d[4], d[7] );
			double maxCost = max( d[1], d[4], d[7] );
			double costRange = maxCost - minCost;
			
			double minStab = min( d[2], d[5], d[8] );
			double maxStab = max( d[2], d[5], d[8] );
			double stabRange = maxStab - minStab;
			
			double latLat = scaled(d[0], minLat, latRange );
			double latCost = scaled(d[1], minCost, costRange );
			double latStab = scaled(d[2], minStab, stabRange );
			
			double costLat = scaled(d[3], minLat, latRange );
			double costCost = scaled(d[4], minCost, costRange );
			double costStab = scaled(d[5], minStab, stabRange );
			
			double stabLat = scaled(d[6], minLat, latRange );
			double stabCost = scaled(d[7], minCost, costRange );
			double stabStab = scaled(d[8], minStab, stabRange );
			
			double algoLat = scaled(d[9], minLat, latRange );
			double algoCost = scaled(d[10], minCost, costRange );
			double algoStab = scaled(d[11], minStab, stabRange );
			
			buffer.append(key);
			
			buffer.append(","+minLat+","+maxLat+","+latRange);
			buffer.append(","+minCost+","+maxCost+","+costRange);
			buffer.append(","+minStab+","+maxStab+","+stabRange);
			
			buffer.append(","+latLat+","+latCost+","+latStab);
			buffer.append(","+costLat+","+costCost+","+costStab);
			buffer.append(","+stabLat+","+stabCost+","+stabStab);
			buffer.append(","+algoLat+","+algoCost+","+algoStab);
			
			buffer.append(","+dist(algoLat, algoCost, algoStab));
			
			buffer.append("\n");
		}
		return buffer.toString();
	}
	
	private void writeToFile(String filename, String result) {
		try {
			BufferedWriter out = new BufferedWriter(new FileWriter(filename));
			out.write(result);
			out.flush();
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private Map<String, Double[]> getData(String filename) {
		Map<String, Double[]> val = new LinkedHashMap<String, Double[]>();
		try {
			BufferedReader in = new BufferedReader(new FileReader(new File(filename)));
			String line = "";
			while ( ( line=in.readLine() ) != null ) {
				String tokens[] = line.split(",");
				String key = tokens[0];
				Double[] values = { Double.valueOf(tokens[1]), 
									Double.valueOf(tokens[2]),
									Double.valueOf(tokens[3]),
									Double.valueOf(tokens[4]),
									Double.valueOf(tokens[5]),
									Double.valueOf(tokens[6]),
									Double.valueOf(tokens[7]),
									Double.valueOf(tokens[8]),
									Double.valueOf(tokens[9]),
									Double.valueOf(tokens[10]),
									Double.valueOf(tokens[11]),
									Double.valueOf(tokens[12])
									};
				val.put(key, values);
			}
		}catch (FileNotFoundException e) {
			e.printStackTrace();
		}catch (IOException ioe) {
			ioe.printStackTrace();
		}
		return val;
	}
	
	private double scaled(double cur, double min, double range) {
		if ( range == 0 )
			return 0;
		else
			return ( cur - min ) / range;
	}
	
	private double dist(double latT, double costT, double stabT) {
		double dist = Math.sqrt( Math.pow(latT, 2) + Math.pow(costT, 2) + Math.pow(stabT, 2) );
		return dist;
	}
	
	private double min(double valA, double valB, double valC) {
		return Math.min( Math.min(valA, valB), valC );
	}
	
	private double max(double valA, double valB, double valC) {
		return Math.max( Math.max(valA, valB), valC );
	}
	
	public static void main(String args[]) {
		ScaledRelativePerformance app = new ScaledRelativePerformance();
		String input = "fw_08.log";
		String output = "fw_08_relative_performance.csv";
		app.getResult(input, output);
	}
	
}//end of class ScaledRelativePerformance
